package com.bah.tract.client.workstore.tol;

import java.io.IOException;
import java.io.InputStream;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

public class TOLResponseParser {

	private static final class TOLDataHandler extends DefaultHandler {
		private final TOLData data;
		private boolean inChargeNumber = false;
		private boolean doneCharges = false;
		private boolean inTaxCode = false;
		private StringBuilder buffer = null;
		private String value;

		private TOLDataHandler(TOLData data) {
			this.data = data;
		}

		@Override
		public final void characters(final char[] arg0, final int arg1,
				final int arg2) throws SAXException {
			if (buffer != null) {
				buffer.append(arg0, arg1, arg2);
			}
		}

		@Override
		public void endElement(final String url,
				final String localName, final String qName)
				throws SAXException {
			if (inChargeNumber && "SELECT".equals(localName)) {
				inChargeNumber = false;
			} else if (inTaxCode && "SELECT".equals(localName)) {
				inChargeNumber = false;
			} else if ((inTaxCode || inChargeNumber)
					&& "OPTION".equals(localName)) {
				final String label = buffer.toString();
				buffer = null;
				if (inTaxCode) {
					if (value != null) {
						data.getTaxLocations().put(label.trim(), value);
					}
				} else { // must be in charge numbers
					if (!doneCharges) {
						// There is a blank line before the absence
						// codes
						// start
						if ("".equals(label.trim()) && "".equals(value)) {
							doneCharges = true;
						} else if (value != null) {
							data.getChargeNumbers().put(label.trim(),
									value);
						}
					}

				}
			}
		}

		@Override
		public void startElement(final String uri,
				final String localName, final String qName,
				final Attributes atts) throws SAXException {
			if ("SELECT".equals(localName)) {
				final String field = atts.getValue("", "name");
				if ("charge_number".equals(field)) {
					inChargeNumber = true;
				} else if ("tax_code".equals(field)) {
					inTaxCode = true;
				}
			}
			if ("INPUT".equals(localName)) {
				final String field = atts.getValue("", "name");
				if ("timecard_id".equals(field)) {
					data.setTimecardId(atts.getValue("", "value"));
				} else if ("time_period_code".equals(field)) {
					data.setTimePeriodCode(atts.getValue("", "value"));
				}
			} else if ((inTaxCode || inChargeNumber)
					&& "OPTION".equals(localName)) {
				value = atts.getValue("", "value");
				buffer = new StringBuilder();
			}
		}
	}

	public final TOLData parseResponse(final InputStream is) throws IOException {
		final TOLData data = new TOLData();
		try {
			final XMLReader reader = XMLReaderFactory
					.createXMLReader("org.cyberneko.html.parsers.SAXParser");
			reader.setContentHandler(new TOLDataHandler(data));

			reader.parse(new InputSource(is));
		} catch (final SAXException e) {
			throw new IOException(e);
		}
		return data;
	}

}
